package cn.tedu.charging.cost.service.impl;

import cn.tedu.charging.cost.dao.repository.ChargingDataRepository;
import cn.tedu.charging.cost.dao.repository.ChargingRuleRepository;
import cn.tedu.charging.cost.dao.repository.CostRuleCacheRepository;
import cn.tedu.charging.cost.pojo.po.ChargingDataPO;
import cn.tedu.charging.cost.pojo.po.CostRulePO;
import cn.tedu.charging.cost.service.CostService;
import cn.tedu.common.pojo.param.ChargingProcessParam;
import cn.tedu.common.pojo.vo.ChargingProcessVO;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.common.recycler.Recycler;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
//@Slf4j
@Service
public class CostServiceImpl implements CostService {
    private static final Logger log= LoggerFactory.getLogger(CostServiceImpl.class);
    /**依赖ES数据层对象*/
    @Autowired
    private ChargingDataRepository chargingDataRepository;
    /**依赖Redis数据层对象*/
    @Autowired
    private CostRuleCacheRepository costRuleCacheRepository;
    /**依赖MySQL数据层对象*/
    @Autowired
    private ChargingRuleRepository chargingRuleRepository;
    /**
     * 思考：计费
     * 1)如何判断第一次计费，还是非第一次计费
     * 2)计费的结果要同步给客户端，还有存储到哪里？ES数据库
     * @param chargingProcessParam
     * @return
     */
    @Override
    public ChargingProcessVO calculateCost(ChargingProcessParam chargingProcessParam) {
      //1.从ES中获取充电时序数据
      ChargingDataPO chargingDataPO =
                chargingDataRepository.findByOrderNo(chargingProcessParam.getOrderNo());
      if(chargingDataPO==null){//值为null表示这是第一次计费
          chargingDataPO=new ChargingDataPO();
          BeanUtils.copyProperties(chargingProcessParam,chargingDataPO);
          chargingDataPO.setCount(1);//设置这是第一次计费数据
          chargingDataRepository.save(chargingDataPO);
      }
      //2.获取计费规则
        CostRulePO matchedRule = getCostRulePO(chargingProcessParam);
        //3.进行费用的计算
        if(matchedRule!=null){
            if(chargingDataPO.isFirst()){
               //第一次计费
                doFirstCost(chargingProcessParam,matchedRule,chargingDataPO);
            }else{
               //不是第一次计费
                doNotFirstCost(chargingProcessParam,matchedRule,chargingDataPO);
            }
        }else{
           log.debug("场站{}没有在{}匹配到对应的计费规则",chargingProcessParam.getStationId(),LocalDateTime.now());
        }
        //4.返回计费结果
        ChargingProcessVO chargingProcessVO=new ChargingProcessVO();
        BeanUtils.copyProperties(chargingDataPO,chargingProcessVO);
        return chargingProcessVO;
    }

    @Nullable
    private CostRulePO getCostRulePO(ChargingProcessParam chargingProcessParam) {
        //2.1获取所有匹配规则
        List<CostRulePO> costRules = costRuleCacheRepository.getCostRuleByStationId(chargingProcessParam.getStationId());
        if(costRules==null){
            costRules = chargingRuleRepository.selectCostRules(chargingProcessParam.getStationId());
            costRuleCacheRepository.saveCostRule(chargingProcessParam.getStationId(),costRules);
        }
        //2.2 按时间匹配规则
        //2.2.1获取当前时间
        int hour = LocalDateTime.now().getHour();
        //2.2.2匹配规则
        CostRulePO matchedRule = null;
        for (CostRulePO costRule : costRules) {
            if(hour>=costRule.getStartTime()&&hour<=costRule.getEndTime()){
                //匹配到了规则，开始计费
                if(costRule.getGunType()== chargingProcessParam.getGunType()) {
                    matchedRule = costRule;
                    break;
                }
            }
        }
        return matchedRule;
    }

    /**第一次计费*/
    private void doFirstCost(
            ChargingProcessParam chargingProcessParam,
            CostRulePO costRulePO,
            ChargingDataPO chargingDataPO){
        //1.获取充电量(截止到当前时间)
        Float chargingCapacity =
                chargingProcessParam.getChargingCapacity();
        //2.基于电量和价格计算出费用
        BigDecimal add =
              costRulePO.getPowerFee().add(costRulePO.getServiceFee());
        BigDecimal currentCost =
                add.multiply(BigDecimal.valueOf(chargingCapacity));
        //3.更新ES存储订单的金额数据
        chargingDataPO.setChargingCapacity(chargingCapacity);
        chargingDataPO.setTotalCost(currentCost);
        chargingDataRepository.save(chargingDataPO);
    }
     /**第一次计费*/
    private void doNotFirstCost(
            ChargingProcessParam chargingProcessParam,
            CostRulePO costRulePO,
            ChargingDataPO chargingDataPO){
        //1.获取总充电量(截止到当前时间)，这个总充电量是从开始到现在充的总电量
        //1.1 总电量
        Float chargingCapacity = chargingProcessParam.getChargingCapacity();
        chargingDataPO.setCount(chargingDataPO.getCount()+1);
        //1.2 当前这个时间段的充电量(总电量减去上一次同步的充电量)
        BigDecimal concurrentChargingCapacity =
                BigDecimal.valueOf(chargingCapacity).subtract(BigDecimal.valueOf(chargingDataPO.getChargingCapacity()));
        //2.基于电量和价格计算出费用
        BigDecimal fee = costRulePO.getPowerFee().add(costRulePO.getServiceFee());
        BigDecimal currentCost = fee.multiply(concurrentChargingCapacity);
        //3.更新ES存储订单的金额数据
        chargingDataPO.setChargingCapacity(chargingCapacity);
        chargingDataPO.setTotalCost(currentCost);
        chargingDataRepository.save(chargingDataPO);
    }


}
